#ifndef __PROCESS_POOL_HPP__
#define __PROCESS_POOL_HPP__

#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <functional>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <time.h>
#include "Task.hpp"

const int process_num = 5;

using callback_t = std::function<void(int fd)>;

class Channel
{
public:
    Channel()
    {
    }

    Channel(int fd, std::string &name, pid_t pid)
        : _wfd(fd), _name(name), _sub_target(pid)
    {
    }

    void DebugPrint()
    {
        printf("channel name: %s, wfd: %d, pid: %d\n", _name.c_str(), _wfd, _sub_target);
    }

    int GetFd()
    {
        return _wfd;
    }

    std::string GetName()
    {
        return _name;
    }

    pid_t GetPid()
    {
        return _sub_target;
    }

    void Close()
    {
        close(_wfd);
    }

    void Wait()
    {
        pid_t ret_pid = waitpid(_sub_target, nullptr, 0);
    }

private:
    int _wfd;
    std::string _name;
    pid_t _sub_target;
};

class ProcessPool
{
public:
    ProcessPool(int num = process_num)
        : _process_num(num)
    {
        srand(time(nullptr) ^ getpid() ^ 0x777);
    }

    bool InitProcessPool(callback_t cb)
    {
        for (int i = 0; i < process_num; i++)
        {
            sleep(1);
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                return false;
            }
            pid_t pid = fork();
            if (pid < 0)
            {
                return false;
            }
            if (pid == 0)
            {
                close(pipefd[1]);
                std::cout << "进程:" << getpid() << "关闭了:";
                for(auto& e : _channels)
                {
                    std::cout << e.GetFd() << ",";
                    e.Close();
                }
                std::cout << std::endl;
                cb(pipefd[0]);
                exit(0);
            }
            close(pipefd[0]);
            std::string name = "channel-" + std::to_string(i);
            _channels.emplace_back(pipefd[1], name, pid);
        }
        return true;
    }
    void ControlSubProcess()
    {
        std::cout << "父进程开始控制" << std::endl;
        int index = 0;
        while (1)
        {
            int who = index++;
            index %= _channels.size();
            int x = 1;
            std::cout << "选择信道:" << _channels[who].GetName() << ", subtarget:" << _channels[who].GetPid() << std::endl;
            write(_channels[who].GetFd(), &x, sizeof(x));
            sleep(2);
        }
    }

    void _ControlSubProcess(int &index)
    {
        int who = index++;
        index %= _channels.size();
        int x = rand() % tasks.size();
        std::cout << "选择信道:" << _channels[who].GetName() << ", subtarget:" << _channels[who].GetPid() << std::endl;
        write(_channels[who].GetFd(), &x, sizeof(x));
        sleep(2);
    }

    void ControlSubProcess(int count)
    {
        std::cout << "父进程开始控制" << std::endl;
        int index = 0;
        while(count--)
        {
            _ControlSubProcess(index);
        }
    }

    void WaitSubProcess()
    {
        // for (auto &e : _channels)
        // {
        //     e.Close();
        // }
        // for (auto &e : _channels)
        // {
        //     e.Wait();
        //     std::cout << "回收子进程成功:" << e.GetFd() << std::endl;
        // }
        // for(int i = _channels.size() - 1; i >= 0; i--)
        // {
        //     _channels[i].Close();
        //     _channels[i].Wait();
        // }
        for(auto& e : _channels)
        {
            e.Close();
            e.Wait();
        }
    }

private:
    std::vector<Channel> _channels;
    int _process_num;
};

#endif